'use strict';

const Service = require('egg').Service;
const Sequelize = require('sequelize');
const Op = Sequelize.Op;

class StarService extends Service {
    // 歌星列表
    async page(query) {
      const { ctx } = this;
      let config = {
        where:{
          isDel:0
        },
        order:[
          ['createTime', 'DESC']
        ],
        attributes: {
          include: [
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM collection
                  WHERE
                      collection.cid = star.id
                      AND
                      collection.type = 2
              )`),
              'collectionNum'
            ],
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM likes
                  WHERE
                      likes.lid = star.id
                      AND
                      likes.type = 2
              )`),
              'likesNum'
            ],
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM comment
                  WHERE
                      comment.cid = star.id
                      AND
                      comment.type = 2
                      AND
                      comment.isDel = 0
              )`),
              'commentNum'
            ]
          ],
          exclude: ['isDel','delTime'],
        }
      };
      if(query.name){
        config.where.name = {
          [Op.like]:`%${query.name}%`
        }
      }
      if(!query.pageNO){
        query.pageNO = 1;
      }
      if(!query.pageSize){
        query.pageSize = 10;
      }
      config.offset = (query.pageNO-1)*query.pageSize;
      config.limit = query.pageSize;
      return await ctx.model.Star.findAndCountAll(config);
    }

    // 歌星详情
    async detail(query) {
      const { ctx } = this;
      let config = {
        where:{
          isDel:0,
          id:query.id
        },
        attributes: {
          include: [
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM collection
                  WHERE
                      collection.cid = star.id
                      AND
                      collection.type = 2
              )`),
              'collectionNum'
            ],
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM likes
                  WHERE
                      likes.lid = star.id
                      AND
                      likes.type = 2
              )`),
              'likesNum'
            ],
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM comment
                  WHERE
                      comment.cid = star.id
                      AND
                      comment.type = 2
                      AND
                      comment.isDel = 0
              )`),
              'commentNum'
            ]
          ],
          exclude: ['isDel','delTime']
        }
      };
      return await ctx.model.Star.findOne(config);
    }

    // 歌星添加
    async add(data) {
      const { ctx } = this;
      return await ctx.model.Star.create({
        name:data.name,
        desc:data.desc?data.desc:'',
        headimg:data.headimg?data.headimg:'',
        status:data.status,
        createTime:new Date().getTime(),
        updateTime:new Date().getTime(),
        delTime:0
      });
    }

    // 歌星编辑
    async edit(data) {
      const { ctx } = this;
      return await ctx.model.Star.update({
        name:data.name,
        desc:data.desc?data.desc:'',
        headimg:data.headimg?data.headimg:'',
        status:data.status,
        updateTime:new Date().getTime()
      },{
        where:{
          id:data.id
        }
      });
    }

    // 歌星删除
    async del(data) {
      const { ctx } = this;
      const t = await ctx.model.transaction();
      try{
        let [collectionDel,likeDel,commentDel,starDel] = await Promise.all(
          [
            // 删除收藏
            ctx.model.Collection.destroy({
              where: {
                type:2,
                cid:data.id
              },
              transaction:t
            }),
            // 删除点赞
            ctx.model.Likes.destroy({
              where: {
                type:2,
                lid:data.id
              },
              transaction:t
            }),
            // 删除评论
            ctx.model.Comment.update({
              isDel:1,
              delTime:new Date().getTime()
            },{
              where:{
                type:2,
                cid:data.id
              },
              transaction:t
            }),
            // 删除歌星
            ctx.model.Star.update({
              isDel:1,
              delTime:new Date().getTime()
            },{
              where:{
                id:data.id
              },
              transaction:t
            })
          ]
        );
        if(!starDel[0]){
          throw new Error('error');
        }
        await t.commit();
        return starDel;
      }catch(e){
        await t.rollback();
        return [0];
      }
    }

    // 歌星修改状态
    async status(data) {
      const { ctx } = this;
      return await ctx.model.Star.update({
        status:data.status,
        updateTime:new Date().getTime()
      },{
        where:{
          id:data.id
        }
      });
    }

    // 递归获取评论集合
    async recursiveComment(arr,id){
      const { ctx } = this;
      let config = {
        where:{
          isDel:0,
          pid:id,
          type:2
        },
        attributes: ['id']
      };
      let result = await ctx.model.Comment.findOne(config);
      if(result){
        arr.push(result.id);
        await this.recursiveComment(arr,result.id);
      }
    }

    // 歌星评论列表
    async commentPage(query) {
      const { ctx } = this;
      let config = {
        where:{
          isDel:0,
          cid:query.cid,
          type:2
        },
        order:[
          ['createTime', 'DESC']
        ],
        attributes: {
          include: [
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM likes
                    WHERE
                        likes.lid = comment.id
                        AND
                        likes.type = 5
                )`),
              'likesNum'
            ],
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM comment AS c
                    WHERE
                        c.pid = comment.id
                        AND
                        c.type = 5
                        AND
                        c.isDel = 0
                )`),
              'commentNum'
            ],
            [Sequelize.col('user.account'), 'account'],
            [Sequelize.col('user.nickname'), 'nickname']
          ],
          exclude: ['isDel','delTime','type'],
        },
        include: [{
          model: ctx.model.User,
          as: 'user',
          duplicating:false,
          required:false,
          attributes: []
        }],
        distinct: true
      };
      config.where.pid = query.pid?query.pid:0;
      if(!query.pageNO){
        query.pageNO = 1;
      }
      if(!query.pageSize){
        query.pageSize = 10;
      }
      config.offset = (query.pageNO-1)*query.pageSize;
      config.limit = query.pageSize;
      return await ctx.model.Comment.findAndCountAll(config);
    }

    // 歌星评论详情
    async commentDetail(query) {
      const { ctx } = this;
      let config = {
        where:{
          isDel:0,
          id:query.id,
          type:2
        },
        attributes: {
          include: [
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM likes
                    WHERE
                        likes.lid = comment.id
                        AND
                        likes.type = 5
                )`),
              'likesNum'
            ],
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM comment AS c
                    WHERE
                        c.pid = comment.id
                        AND
                        comment.type = 5
                        AND
                        comment.isDel = 0
                )`),
              'commentNum'
            ],
            [Sequelize.col('user.account'), 'account'],
            [Sequelize.col('user.nickname'), 'nickname']
          ],
          exclude: ['isDel','delTime','type']
        },
        include: [{
          model: ctx.model.User,
          as: 'user',
          duplicating:false,
          required:false,
          attributes: []
        }]
      };
      return await ctx.model.Comment.findOne(config);
    }

    // 歌星评论删除
    async commentDel(data) {
      const { ctx } = this;
      const t = await ctx.model.transaction();
      try{
        let delArr = [data.id];
        await this.recursiveComment(delArr,data.id);
        let [likeDel,commentDel] = await Promise.all(
          [
            // 删除点赞
            ctx.model.Likes.destroy({
              where: {
                type:5,
                lid:{
                  [Op.in]:delArr
                }
              },
              transaction:t
            }),
            // 删除评论
            ctx.model.Comment.update({
              isDel:1,
              delTime:new Date().getTime()
            },{
              where:{
                type:2,
                id:{
                  [Op.in]:delArr
                }
              },
              transaction:t
            }),
          ]
        );
        if(!commentDel[0]){
          throw new Error('error');
        }
        await t.commit();
        return commentDel;
      }catch(e){
        await t.rollback();
        return [0];
      }
    }

    // 歌星评论状态修改
    async commentStatus(data) {
      const { ctx } = this;
      return await ctx.model.Comment.update({
        status:data.status,
        updateTime:new Date().getTime()
      },{
        where:{
          id:data.id,
          type:2
        }
      });
    }

    // 获取歌星总数
    async getNum() {
      const { ctx } = this;
      return await ctx.model.Star.findOne({
        attributes: [
            [
              Sequelize.literal(`(
                  SELECT COUNT(*)
                  FROM star
                  WHERE
                      star.isDel = 0
              )`),
              'num'
            ]
          ]
      });
    }

    // 获取所有歌星播放量
    async getStarPlayNum(){
      const { ctx } = this;
      let config = {
        where:{
          isDel:0
        },
        attributes: {
          include: [
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM collection
                    WHERE
                        collection.cid = star.id
                        AND
                        collection.type = 2
                )`),
              'collectionNum'
            ],
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM likes
                    WHERE
                        likes.lid = star.id
                        AND
                        likes.type = 2
                )`),
              'likesNum'
            ],
            [
              Sequelize.literal(`(
                    SELECT COUNT(*)
                    FROM comment
                    WHERE
                        comment.cid = star.id
                        AND
                        comment.type = 2
                        AND
                        comment.isDel = 0
                )`),
              'commentNum'
            ],
            [
              Sequelize.literal(`(
                    SELECT SUM(music.playNum)
                    FROM music
                    WHERE
                        music.sid = star.id
                        AND
                        music.isDel = 0
                )`),
              'playNum'
            ]
          ],
          exclude: ['isDel','delTime'],
        }
      };
      return await ctx.model.Star.findAll(config);
    }
  }

  module.exports = StarService;
